# Build Kernel modules
set(MODULE_NAME qtfs_server)

## First, find the kernel build directory
execute_process(
        COMMAND uname -r
        OUTPUT_VARIABLE KERNEL_RELEASE
        OUTPUT_STRIP_TRAILING_WHITESPACE)
set(KBUILD_DIR /lib/modules/${KERNEL_RELEASE}/build/)
find_file(KERNEL_MAKEFILE NAMES Makefile PATHS ${KBUILD_DIR} NO_DEFAULT_PATH)
if (NOT KERNEL_MAKEFILE)
    message(FATAL_ERROR "There is no Makefile in ${KBUILD_DIR}!")
endif ()

## Second, gather the source files
set(COMM_SRC_FILES
        ${QTFS_BASE_DIR}/qtfs_common/conn.c
        ${QTFS_BASE_DIR}/qtfs_common/misc.c
        ${QTFS_BASE_DIR}/qtfs_common/qtfs_check.c
        ${QTFS_BASE_DIR}/qtfs_common/socket.c
        ${QTFS_BASE_DIR}/qtfs_common/symbol_wrapper.c)

set(QTFS_SERVER_SRC_FILES
        ${QTFS_BASE_DIR}/qtfs_server/fsops.c
        ${QTFS_BASE_DIR}/qtfs_server/qtfs-server.c)

set(QTFS_SERVER_MODULE_SRC ${COMM_SRC_FILES} ${QTFS_SERVER_SRC_FILES})

## Third, make the src files accessible to the kernel Makefile
set(MODULE_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/)
set(QTFS_SERVER_KBUILD_FILE "obj-m := ${MODULE_NAME}.o")
foreach (file ${QTFS_SERVER_MODULE_SRC})
    file(RELATIVE_PATH file "${CMAKE_CURRENT_SOURCE_DIR}" "${file}")
    configure_file(${file} ${file} COPYONLY)
    string(REPLACE ".c" ".o" file_obj "${file}")
    set(QTFS_SERVER_KBUILD_FILE "${QTFS_SERVER_KBUILD_FILE}\n${MODULE_NAME}-y += ${file_obj}")
endforeach ()

set(QTFS_SERVER_KBUILD_FILE "${QTFS_SERVER_KBUILD_FILE}\nccflags-y += -I${QTFS_BASE_DIR}/include")
set(QTFS_SERVER_KBUILD_FILE "${QTFS_SERVER_KBUILD_FILE}\nccflags-y += -I${QTFS_BASE_DIR}/ipc")
set(QTFS_SERVER_KBUILD_FILE "${QTFS_SERVER_KBUILD_FILE}\nccflags-y += -I${QTFS_BASE_DIR}/qtfs_server")
set(QTFS_SERVER_KBUILD_FILE "${QTFS_SERVER_KBUILD_FILE}\nccflags-y += -DQTFS_SERVER")

if (DEFINED UDS_TEST_MODE OR DEFINED QTFS_TEST_MODE)
    set(QTFS_SERVER_KBUILD_FILE "${QTFS_SERVER_KBUILD_FILE}\nccflags-y += -DQTFS_TEST_MODE")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUDS_TEST_MODE")
endif ()

## Forth, generate a Kbuild file
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/Kbuild ${QTFS_SERVER_KBUILD_FILE})

## Fifth, add a custom target to build the module
set(MODULE_CMD ${CMAKE_MAKE_PROGRAM} -C ${KBUILD_DIR} M=${CMAKE_CURRENT_BINARY_DIR})
add_custom_command(OUTPUT ${MODULE_NAME}.ko
        COMMAND ${MODULE_CMD} modules
        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
        DEPENDS ${QTFS_SERVER_MODULE_SRC} ${CMAKE_CURRENT_BINARY_DIR}/Kbuild
        VERBATIM)
add_custom_target(${MODULE_NAME} DEPENDS ${MODULE_NAME}.ko)
add_custom_target(${MODULE_NAME}-clean COMMAND ${MODULE_CMD} clean)

# This target helps parsing C files for IDEs like CLion
add_library(dummy-${MODULE_NAME} EXCLUDE_FROM_ALL ${QTFS_SERVER_MODULE_SRC})
target_include_directories(dummy-${MODULE_NAME} PRIVATE
        ${KBUILD_DIR}/include
        ${QTFS_BASE_DIR}/include
        ${QTFS_BASE_DIR}/ipc
        ${QTFS_BASE_DIR}/qtfs_server)
set_target_properties(dummy-${MODULE_NAME} PROPERTIES DEPRECATION "DO NOT BUILD THIS TARGET")